package com.yq.service.annotation;

import com.google.common.collect.Maps;
import com.yq.core.base.entity.HessianEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.remoting.caucho.HessianServiceExporter;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.DispatcherServlet;

import java.util.Map;

@Component
public class AzerothAutoServiceProcessor extends DispatcherServlet implements BeanFactoryPostProcessor {

    private static Logger logger = LoggerFactory.getLogger(AzerothAutoServiceProcessor.class);

    private static Map<String, HessianEntity> builders = Maps.newHashMap();

    /**
     * 用于获取 Spring 注入的 HessianServiceExporter
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        logger.info("***** Hessian Service 自动配置开始**************************************************");

        String[] beanNames = beanFactory.getBeanNamesForAnnotation(AzerothAutoService.class);
        for (String beanName : beanNames) {
            String className = beanFactory.getBeanDefinition(beanName)
                    .getBeanClassName();
            Class<?> clasz = null;
            try {
                clasz = Class.forName(className);
            } catch (ClassNotFoundException e) {
                throw new BeanInitializationException(e.getMessage(), e);
            }

            String id = beanName.replace("Impl", "");
            String registerId = "/" + id;
            builders.put(registerId, new HessianEntity(registerId, id, clasz.getInterfaces()[0].getName()));

            // ============================================================================================

            // 根据每个 clasz 对象，进行构造
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(clasz.getName());
            builder.getBeanDefinition().setAttribute("id", id);
            builder.getBeanDefinition().setAttribute("class", clasz.getName());

            logger.info("bean id="+id+" class="+clasz.getName());
            logger.info("");

            // 注册 clasz 对象
            ((BeanDefinitionRegistry) beanFactory).registerBeanDefinition(id, builder.getBeanDefinition());
        }

        logger.info("***** Hessian Service 自动配置结束**************************************************");
    }

    /**
     * 用于获取 DispatcherServlet 自动注入 Hessian
     */
    @Override
    protected void initStrategies(ApplicationContext context) {

        logger.info("***** 自动注入Hession 自动配置开始**************************************************");

        //将applicationContext转换为ConfigurableApplicationContext
        ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) context;
        // 获取bean工厂并转换为DefaultListableBeanFactory
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory();

        logger.info("HessianServiceExporter数据="+builders);

        // 注册
        for (String key : builders.keySet()) {
            HessianEntity hession = builders.get(key);

            BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(HessianServiceExporter.class);
            builder.getBeanDefinition().setAttribute("id", hession.getId());
            builder.getBeanDefinition().setAttribute("class", HessianServiceExporter.class);
            builder.addPropertyReference("service", hession.getService());
            builder.addPropertyValue("serviceInterface", hession.getServiceInterface());

            logger.info("bean id="+hession.getId()+" class="+HessianServiceExporter.class);
            logger.info("property name=service ref="+hession.getService());
            logger.info("property service=serviceInterface value="+hession.getServiceInterface());
            logger.info("");

            beanFactory.registerBeanDefinition(key, builder.getBeanDefinition());
        }

        builders = null;

        super.initStrategies(context);

        logger.info("***** 自动注入Hession 自动配置结束**************************************************");
    }
}
